package com.hulk.dryad.common.util;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;

import com.google.common.collect.Maps;
import com.hulk.dryad.common.constant.CommonConstants;
import com.hulk.dryad.common.constant.SecurityConstants;
import jodd.util.StringPool;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.*;

/**
 * @author hulk
 */
@Slf4j
public class SignUtil {

	public static final String SIGNATURE = "signature";
    /**
     * 签名
     *
     * @param data 明文map
     */
    public static String sign(Map<String, Object> data) {
        return sign(data, SecurityConstants.SIGN_KEY_VALUE) ;
    }

    /**
     * 签名
     *
     * @param data 明文map
     */
    public static String sign(Map<String, Object> data,String key) {
        SortedMap<String, Object> signMap = new TreeMap<>(data);
        String signStr = createSign(signMap,key);
        return DigestUtil.sha256Hex(signStr.getBytes(StandardCharsets.UTF_8));
    }


    /**
     * 验签
     *
     * @param data   明文map
     * @param signed 签名值
     */
    public static boolean verify(@NonNull Map<String, Object> data, @NonNull String signed,@NonNull String key) {
        boolean flag = false;
        SortedMap<String, Object> signMap = new TreeMap<>(data);
        String signStr = createSign(signMap,key);
        String sign = DigestUtil.sha256Hex(signStr.getBytes(StandardCharsets.UTF_8));
        if (StrUtil.equalsIgnoreCase(sign, signed)) {
            flag = true;
        }
        return flag;
    }

    /**
     * 获取签名字符串
     *
     * @param parameters 签名Map
     * @return 签名字符串
     */
    private static String createSign(SortedMap<String, Object> parameters,String key) {

		if(MapUtil.isEmpty(parameters)){
			return null;
		}
        StringBuilder sb = new StringBuilder();
        Set<Map.Entry<String, Object>> es = parameters.entrySet();
		int i = 0;
        for (Map.Entry<String, Object> e : es) {
            String k = e.getKey();
			Object obj =e.getValue();
			String v = (obj == null ||
					 obj instanceof Map ||
					 obj instanceof Iterable ||
					 obj instanceof Iterator ||
					 ArrayUtil.isArray(obj)
			) ? StrUtil.EMPTY: obj.toString();
            //空值不传递，不参与签名组串
            if (StrUtil.isNotBlank(v) && !SIGNATURE.equalsIgnoreCase(k)) {
            	if(i > 0){
					sb.append(StringPool.AMPERSAND);
				}
				sb.append(k).append(StringPool.EQUALS).append(v);
            }
            i++;
        }
        String payload ;
        if(StrUtil.isBlank(key)){
			payload = sb.toString();
		}else {
			payload = sb.append(StringPool.AMPERSAND).append(SecurityConstants.SIGN_KEY_NAME).append(StringPool.EQUALS).append(key).toString();
		}
        //排序后的字符串
        return payload;
    }

    public static void main(String[] args) {
        Map<String, String> map = Maps.newHashMap();
        map.put("loginNo", "11111111111");
        map.put("password", "admin123");
        map.put("loginType", "PWD");
        map.put("loginChannel", "60C3312C26AE24DFF5A7AAA3A71730F11D4D2C7C057F88F0926B272AF9B72D95");
        map.put("loginIp", "127.0.0.1");
        map.put("imei", "123");
        map.put("lbs", "lbs");
        map.put("oem", "oem");
        map.put("browser", "browser");
        map.put("os", "os");
        map.put("loginTime", "201901171004");
        SortedMap<String, Object> signMap = new TreeMap<>(map);
        String signStr = createSign(signMap,SecurityConstants.SIGN_KEY_VALUE);

        String sign = DigestUtil.sha256Hex(signStr.getBytes(StandardCharsets.UTF_8));
        System.out.println(sign);

    }


}
